#nullable enable

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using PHMEE.CommonUtils;
using PHMEE.Localization;
using Volo.Abp.Application.Dtos;

namespace PHMEE.EnergyEfficiency;

public class AnalogSignalAppService : PHMEEAppService, IAnalogSignalAppService
{
    private readonly IPHMEETimeProvider _phmeeTimeProvider;
    private readonly IAnalogTDRepository _analogTDRepository;

    public AnalogSignalAppService(IPHMEETimeProvider phmeeTimeProvider, IAnalogTDRepository analogTDRepository)
    {
        LocalizationResource = typeof(EnergyEfficiencyResource);
        
        _phmeeTimeProvider = phmeeTimeProvider;
        _analogTDRepository = analogTDRepository;
    }

    // 获取实时模拟量信号
    public async Task<List<AnalogGroupDto>> GetRealtimeAnalogSignalsAsync(Guid vesselId)
    {
        var utcNow = _phmeeTimeProvider.GetUtcNow();
        
        // 防止数据同步延迟导致不显示数据，所以时间范围放宽到一小时
        
        // TODO: 在没有实际数据时，先往前查一个月，查到所有测试数据，发版时需调整
        var startTime = utcNow.AddMonths(-6);
        
        var analogSignals = await _analogTDRepository.GetLatestByDateTimeCloseCloseAsync(vesselId, startTime, utcNow);

        var result = analogSignals.GroupBy(a => a.AmsGroup).Select(g =>
        {
            return new AnalogGroupDto
            {
                AmsGroup = g.Key,
                GroupIndex = g.First().GroupIndex,
                // 实时数据组内按照 TagName 排序
                AnalogSignals = g.OrderBy(a => a.TagName)
                    .Select(a => new AnalogSignalDto
                    {
                        Ts = a.Ts,
                        TagName = a.TagName,
                        TagDesc = a.TagDesc,
                        V = a.V,
                        U = a.U.ToDisplayString()
                    })
            };
        }).OrderBy(x => x.GroupIndex).ToList();
        
        return result;
    }
    
    // 查询模拟量信号
    public async Task<PagedResultDto<AnalogSignalDto>> GetAnalogSignalsAsync(Guid vesselId, string? tagName, string? tagDescription, DateTime startDateTime, DateTime endDateTime, int skipCount, int maxResultCount)
    {
        List<string>? matchedTagdescs = null;
        if (!string.IsNullOrWhiteSpace(tagDescription))
        {
            tagDescription = tagDescription.Trim();
            
            var allDigitalTagdesc = await _analogTDRepository.GetAllAnalogTagdescAsync(vesselId);
            matchedTagdescs = allDigitalTagdesc.Where(d => d.Contains(tagDescription)).ToList();
        }
        
        var (totalCount, analogSignals) = await _analogTDRepository.GetAnalogSignalsAsync(vesselId, tagName, matchedTagdescs, startDateTime, endDateTime, skipCount, maxResultCount);
        
        var analogSignalDtos = analogSignals.Select(d => new AnalogSignalDto
        {
            Ts = d.Ts,
            TagName = d.TagName,
            TagDesc = d.TagDesc,
            V = d.V,
            U = d.U.ToDisplayString()
        }).ToList();

        return new PagedResultDto<AnalogSignalDto>(totalCount, analogSignalDtos);

        // if (string.IsNullOrWhiteSpace(tagName) && string.IsNullOrWhiteSpace(tagDescription))
        // {
        //     throw new UserFriendlyException(L[PHMEEEnergyEfficiencyErrorCodes.TagNameAndDescriptionCannotBeBothEmpty], PHMEEEnergyEfficiencyErrorCodes.TagNameAndDescriptionCannotBeBothEmpty);
        // }
        //
        // if (!string.IsNullOrWhiteSpace(tagName))
        // {
        //     tagName = tagName.Trim();
        //     
        //     var analogSignals = await _analogTDRepository.GetAnalogSignalsByTagnameAsync(vesselId, tagName, startDateTime, endDateTime);
        //
        //     // AMS 可能取到错误的单位，暂时取出现次数最多的单位，作为正确的单位，丢弃其他单位的数据
        //     var majorityUnit = analogSignals.GroupBy(d => d.U)
        //         .OrderByDescending(g => g.Count())
        //         .First().Key;
        //
        //     return analogSignals.Where(d => d.U == majorityUnit)
        //         .Select(d => new AnalogSignalDto
        //         {
        //             Ts = d.Ts,
        //             TagName = d.TagName,
        //             TagDesc = d.TagDesc,
        //             V = d.V,
        //             U = d.U.ToDisplayString()
        //         }).ToList();
        //     
        // }
        // else if (!string.IsNullOrWhiteSpace(tagDescription))
        // {
        //     tagDescription = tagDescription.Trim();
        //     
        //     var allDigitalTagdesc = await _analogTDRepository.GetAllAnalogTagdescAsync(vesselId);
        //     var matchedTagdescs = allDigitalTagdesc.Where(d => d.Contains(tagDescription));
        //     
        //     var analogSignals = await _analogTDRepository.GetAnalogSignalsByTagdescAsync(vesselId, matchedTagdescs, startDateTime, endDateTime);
        //     
        //     // AMS 可能取到错误的单位，暂时取出现次数最多的单位，作为正确的单位，丢弃其他单位的数据
        //     var majorityUnit = analogSignals.GroupBy(d => d.U)
        //         .OrderByDescending(g => g.Count())
        //         .First().Key;
        //
        //     return analogSignals.Where(d => d.U == majorityUnit)
        //         .Select(d => new AnalogSignalDto
        //         {
        //             Ts = d.Ts,
        //             TagName = d.TagName,
        //             TagDesc = d.TagDesc,
        //             V = d.V,
        //             U = d.U.ToDisplayString()
        //         }).ToList();
        // }
        // else
        // {
        //     return [];
        // }
    }
    
    // // 根据 tagNames 查询每个 tag 最新的一条数据
    // public async Task<List<AnalogSignalDto>> GetAnalogSignalsByTagnamesAsync(Guid vesselId, List<string> tagNames)
    // {
    //     var utcNow = _phmeeTimeProvider.GetUtcNow();
    //     
    //     var analogSignals = await _analogTDRepository.GetAnalogSignalsByTagnamesAsync(vesselId, tagNames, utcNow);
    //     
    //     return analogSignals.Select(d => new AnalogSignalDto
    //     {
    //         Ts = d.Ts,
    //         TagName = d.TagName,
    //         TagDesc = d.TagDesc,
    //         V = d.V,
    //         U = d.U.ToDisplayString()
    //     }).ToList();
    // }
}